package org.yan.stock.server.core;

import java.util.Calendar;
import java.util.Locale;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.yan.stock.server.client.Client;
import org.yan.stock.server.client.ClientRegistry;

public class ResourceController extends Thread {
	
	private final ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
	
	private double threshold;
	
	private int refreshRate;
	
	public ResourceController(double threshold, int refreshRate) {
		this.threshold = threshold;
		this.refreshRate = refreshRate;
	}
	
	public void init() {}

	public void run() {
		super.run();
		init();
		Client client = null;
		while(true) {
			if(isOpening()) {
				final Queue<Client> clientQueue = ClientRegistry.getRegistry().getRegisters();
				while(clientQueue.size() > 0) {
					client = clientQueue.poll();
					if(client == null) {
						break;
					}
					pool.execute(new ParseCommand(client, threshold));
				}
			}
			rest();
		}
	}
	
	/**
	 *  If date  is in the range of monday and friday,
	 *  time is in the range of 09:30 and 11:30, or in the range of 13:00 and 15:00
	 *  return true. 
	 */
	private  boolean isOpening() {
		Calendar cale = Calendar.getInstance(Locale.CHINA);
		long now = cale.getTimeInMillis();
		int day = cale.get(Calendar.DAY_OF_WEEK);
		if(day > 1 && day < 6) {
			cale.set(Calendar.HOUR, 9);
			cale.set(Calendar.MINUTE, 30);
			cale.set(Calendar.MILLISECOND, 0);
			if(cale.getTimeInMillis() - now <= 0){
				cale.set(Calendar.HOUR, 11);
				cale.set(Calendar.MINUTE, 30);
				if(cale.getTimeInMillis() - now >= 0) {
					return true;
				}
				else {
					cale.set(Calendar.HOUR, 13);
					cale.set(Calendar.MINUTE, 00);
					if(cale.getTimeInMillis() - now <= 0) {
						cale.set(Calendar.HOUR, 15);
						cale.set(Calendar.MINUTE, 00);
						if(cale.getTimeInMillis() - now >= 0) {
							return true;
						}
					}
				}
			}
		}
		return false;
	}
	
	private void rest() {
		long restTime = 0l;
		Calendar cale = Calendar.getInstance(Locale.CHINA);
		if (canClosed(cale)) {
			if (cale.get(Calendar.DAY_OF_WEEK) == 6) {
				restTime = getRestTime(cale, 3); // over the weekend
			} else {
				restTime = getRestTime(cale, 1); // over the night
			}
		} else {
			restTime = refreshRate*1000l;
		}
		try {
			Thread.sleep(restTime);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * If the time is big than the spec time(yyyyMMdd 14:mm:00), return true
	 * @param cale
	 * @return
	 */
	private boolean canClosed(Calendar cale) {
		cale.set(Calendar.MILLISECOND, 0);
		long now = cale.getTimeInMillis();
		int minute = 60 - refreshRate;
		cale.set(Calendar.HOUR_OF_DAY, 14);
		cale.set(Calendar.MINUTE, minute);
		cale.set(Calendar.SECOND, 0);
		return now >= cale.getTimeInMillis();
	}
	
	/**
	 * Fetch the rest time of the spec day(yyyyMMdd 09:30:00)
	 * @param cale
	 * @param overDays
	 * @return
	 */
	private long getRestTime(Calendar cale, int overDays) {
		long start = cale.getTimeInMillis();
		cale.add(Calendar.DAY_OF_YEAR, overDays);
		cale.set(Calendar.HOUR_OF_DAY, 9);
		cale.set(Calendar.MINUTE, 30);
		return cale.getTimeInMillis() - start; //over the weekend
	}
	
}
